package codefactroy

import (
	"gitee.com/ichub/goconfig/common/base/basedto"
	"gitee.com/ichub/goconfig/common/base/baseutils/fileutils"
	"gitee.com/ichub/goconfig/common/base/baseutils/stringutils"
	"gitee.com/ichub/goconfig/common/ichublog"
	"gitee.com/ichub/goconfig/godi/internal/didto"
	"github.com/duke-git/lancet/fileutil"
	"github.com/sirupsen/logrus"
	"path/filepath"
	"strings"
)

const tEMPLATE_CODE_FILE = "config/di/template/struct_init.template"

func MakeDi(dto *didto.DiDto) error {
	var cf = FindBeanCodeFactroy()
	cf.Make(dto)
	return cf.WriteStructFile()

}

type CodeFactroy struct {
	basedto.BaseEntity
	rootdir string

	*didto.DiDto
	ExistNewStruct bool
	params         map[string]string
}

func NewCodeFactroy() *CodeFactroy {
	var cf = &CodeFactroy{
		rootdir:        fileutils.FindRootDir(),
		params:         make(map[string]string),
		DiDto:          didto.NewDiDto(),
		ExistNewStruct: true,
	}
	cf.OutPath = "./"
	cf.InitProxy(cf)
	return cf
}

func (cf *CodeFactroy) Path() string {
	return cf.OutPath
}

func (cf *CodeFactroy) SetPath(outpath string) {
	cf.OutPath = outpath
}

func (cf *CodeFactroy) Make(dto *didto.DiDto) {

	cf.DiDto = dto
	cf.MakeToParam()
}

func (cf *CodeFactroy) MakeToParam() {
	if len(cf.NewStructName) == 0 {
		cf.NewStructName = "New" + cf.StructName
	}
	cf.params["SinglePKG"] = cf.PkgName
	cf.params["SingleStruct"] = cf.StructName
	cf.params["NewSingle"] = "&" + cf.StructName + "{}"
	if cf.ExistNewStruct {
		cf.params["NewSingle"] = cf.NewStructName + "()"
	}
}

func (cf *CodeFactroy) ReadTemplate() (string, error) {

	return fileutil.ReadFileToString(cf.rootdir + "/" + tEMPLATE_CODE_FILE)

}

func (cf *CodeFactroy) ParseParams() (string, error) {

	var content, err = cf.ReadTemplate()
	if err != nil {
		logrus.Error(err)
		return "", err
	}
	for k, v := range cf.params {
		content = strings.ReplaceAll(content, "{{."+k+"}}", v)
	}
	return content, err

}

func (cf *CodeFactroy) WriteFile(filename string) error {

	var params, _ = cf.ParseParams()
	path, _ := filepath.Abs(cf.OutPath)
	cf.OutFile = path + "/" + filename

	if !cf.ForceBuild && fileutils.CheckFileExist(cf.OutFile) {
		return nil
	}
	ichublog.Log(cf.ToPrettyString())
	return fileutil.WriteBytesToFile(cf.OutFile, []byte(params))

}

func (cf *CodeFactroy) StructFileName() string {
	return stringutils.Camel2Case(cf.StructName) + "_init.go"
}

func (cf *CodeFactroy) WriteStructFile() error {

	return cf.WriteFile(cf.StructFileName())

}
